
#include <cmath>

#include <BMotion>
#include "member_BMotion.h"

using namespace BWE;

#define member					(*(member_BMotion*)_ptr)
#define member_allocate()		_ptr = new member_BMotion(this)
#define member_release()		delete (member_BMotion*)_ptr

BMotion::BMotion(MotionType type, bool loop)
{
	member_allocate();
	setType(type);
	setLoop(loop);
}
BMotion::BMotion(double startValue, double duration, bool loop)
{
	member_allocate();
	member.time = 0;
	member.loop = loop;
	member.startValue = startValue;
	member.duration = duration;
}
BMotion::~BMotion()
{
	member_release();
}

void BMotion::set(double startValue, double duration, bool loop)
{
	setStartValue(startValue);
	setDuration(duration);
	setLoop(loop);
}

void BMotion::setLoop(bool loop)
{
	member.loop = loop;
}
bool BMotion::loop() const
{
	return member.loop;
}

void BMotion::setType(MotionType type)
{
	member.type = type;
	member.freshFunction();
}
MotionType BMotion::type() const
{
	return member.type;
}

void BMotion::setStartValue(double startValue)
{
	member.startValue = startValue;
}
double BMotion::startValue() const
{
	return member.startValue;
}

void BMotion::setDuration(double duration)
{
	if (member.duration > 0.001)
	{
		member.duration = duration;
	}
}
double BMotion::duration() const
{
	return member.duration;
}

void BMotion::setUnit(double unit)
{
	member.unit = unit;
}
double BMotion::unit() const
{
	return member.unit;
}

bool BMotion::started() const
{
	return member.started;
}
void BMotion::reset()
{
	member.started = false;
	member.startTime = 0;
	member.time = 0;
}
void BMotion::start()
{
	member.started = true;
	member.startTime = 0;
}
void BMotion::pause()
{
	member.started = false;
}
void BMotion::stop()
{
	member.started = false;
	member.startTime = 0;
	member.time = 0;
}

void BMotion::update(double time)
{
	if (!member.func)
		return;

	if (!member.started)
		return;

	if (member.startTime == 0)
		member.startTime = time;

	time -= member.startTime;
	if (time > member.duration)
	{
		if (member.loop)
		{
			time = fmod(time, member.duration);
		}
		else
		{
			time = member.duration;
			member.started = false;
			return;
		}
	}

	double result = member.func(time / member.duration);
	member.value = member.startValue + member.unit * result;
	member.time = time;
}
double BMotion::time() const
{
	return member.time;
}
double BMotion::value() const
{
	return member.value;
}

